package ongd.negocio.gestion;

import java.util.ArrayList;
import java.util.List;
import ongd.negocio.sesion.ControladorSesion;
import ongd.servicios.persistencia.ControladorPersistencia;
import ongd.servicios.persistencia.exceptions.IllegalOrphanException;
import ongd.servicios.persistencia.exceptions.NonexistentEntityException;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;

/**
 * Clase que realizará las operaciones necesarias a los proyectos de
 * cooperación y sensibilización.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 */
public class ControladorProyectoSC extends ControladorProyecto {

    /**
     * Lista de subvenciones que relacionaremos con un proyecto.
     */
    private List<Subvencion> subvenciones;

    /**
     * Constructor de la clase.
     * @param contP controlador Persistencia
     * @param contSesion sesión en la que estamos
     */
    public ControladorProyectoSC(ControladorPersistencia contP, ControladorSesion contSesion) {
        super(contP, contSesion);
        subvenciones = new ArrayList<Subvencion>();
    }

    /**
     * Método que se encargará de crear un proyecto nuevo de sensibilización o cooperación
     * en la base de datos.
     * @param proyecto Proyecto que se va a crear
     * @param lista Lista de personas de contacto asociadas al proyecto
     * @return cadena informando de si se ha creado correctamente o no
     * @throws PreexistingEntityException
     * @throws Exception 
     */
    @Override
    public String crearProyecto(Proyecto proyecto, List<PersonaContacto> lista) throws PreexistingEntityException, Exception {
        //Miramos que el proyecto sea de cooperacion o de sensibilizacion
        if (proyecto.esProyectoCooperacion() || proyecto.esProyectoSensibilizacion()) {
            //Miramos si tienen todos los datos obligatorios.
            if(proyecto.getNombre()!=null && proyecto.getPais()!=null && proyecto.getResponsableONGD()!=null){
                //Comprobamos que las personas tengan datos
                for(PersonaContacto p: lista){
                    if(p.getNombre()==null || p.getDireccion()==null || p.getCargo()==null || p.getTelefono1()==null){
                        return "Incorrecto";
                    }
                }
                //Miramos si el proyecto con ese nombre ya existe y si es asi no creamos el proyecto
                if (buscarProyecto(proyecto.getNombre()) == null) {
                    List<Proyecto> listaP = obtenerProyectos();
                    if (listaP.size() > 0) {
                        //El id del nuevo proyecto, será uno mayor que el ultimo proyecto
                        Proyecto proy = listaP.get(listaP.size() - 1);
                        //Introducimos el id del proyecto, uno mas que el tamaño de la lista
                        proyecto.setIdProyecto(proy.getIdProyecto() + 1);
                    } else {
                        //No hay ningun proyecto, por lo que el id es 1
                        proyecto.setIdProyecto(1);
                    }
                    //Inicio la transacción
                    getContP().iniciarTransaccion();
                    proyecto.setActivo(true);
                    getContP().crearEntidad(proyecto);
                    crearPersonasContacto(lista, proyecto);
                    crearListaSubvenciones(proyecto);
                    //Finalizo la transacción
                    getContP().terminarTransaccion();
                    return "Correcto";
                } else {
                    return "Repetido";
                }
            }else{
               return "Incorrecto"; 
            }
        }
        return "Incorrecto";
    }

    /**
     * Método que borra un proyecto de la base de datos.
     * @param proyecto proyecto que vamsoa  borrar.
     * @return true si el proyecto ha sido borrado correctamente.
     *          false si el proyecto no ha sido borrado.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException 
     */
    @Override
    public boolean borrarProyecto(Proyecto proyecto) throws IllegalOrphanException, NonexistentEntityException {
        boolean subvPendiente = true;
        if (getContP().obtenerEntidad(Proyecto.class, proyecto.getIdProyecto()) != null) {
            //Miramos si alguna de las subvenciones del proyecto esta concedida o rechazada y si es así, no borramos el proyecto
            for (Subvencion s : proyecto.getSubvencionList()) {
                if ((s.estaConcedida() || s.estaRechazada()) && subvPendiente) {
                    subvPendiente = false;
                }
            }
            if (subvPendiente) {
                //Inicio la transaccion
                getContP().iniciarTransaccion();
                //Borramos las subvenciones
                borrarSubvenciones(proyecto.getSubvencionList());
                //Borramos las personas de contacto
                borrarPersonasContacto(proyecto.getPersonaContactoList());
                //Borramos el proyecto
                getContP().destroyEntidad(Proyecto.class, proyecto.getIdProyecto());
                //Finalizo la transacción
                getContP().terminarTransaccion();
                return true;
            }
        }
        return false;
    }

    /**
     * Método que desactiva un proyecto y pone las subvenciones que estaban pendientes a rechazadas.
     * @param proyecto que vamsoa  desactivar.
     * @return true, si se ha desactivado correctamente o false si no es así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    @Override
    public boolean desactivarProyecto(Proyecto proyecto) throws IllegalOrphanException, NonexistentEntityException, Exception {
        if (getContP().obtenerEntidad(Proyecto.class, proyecto.getIdProyecto()) != null) {
            //Inicio la transacción
            getContP().iniciarTransaccion();
            //Ponemos las subvenciones de ese proyecto a rechazadas
            establecerSubvencionesRechazadas(proyecto.getSubvencionList());
            //Editamos el proyecto desactivandolo.
            proyecto.setActivo(false);
//            editarProyecto(proyecto, proyecto.getPersonaContactoList(), false);
            getContP().editarEntidad(proyecto);
            //Finalizo la transacción
            getContP().terminarTransaccion();
            return true;
        }
        return false;
    }

    /**
     * Método que guarda una subvencion para un determinado proyecto.
     * @param subvencion que vamos a guardar.
     * @param p Proyecto para el que es la subvención.
     * @return true si la subvención se ha insertado correctamente.
     * @throws PreexistingEntityException
     * @throws Exception 
     */
    public boolean guardarSubvencion(Subvencion subvencion, Proyecto p) throws PreexistingEntityException, Exception {
        if(subvencion.getEntidad()!=null && subvencion.getFechaPresentacion()!=null
                && getContP().obtenerEntidad(Proyecto.class, p.getIdProyecto())!=null 
                && (p.esProyectoCooperacion() || p.esProyectoSensibilizacion())){
            List<Subvencion> listaSubv = p.getSubvencionList();
            int i;
            if (listaSubv.size() > 0) {
                //El id del nuevo apadrinado, será uno mayor que el ultimo apadrinado
                Subvencion subv = listaSubv.get(listaSubv.size() - 1);
                i = subv.getSubvencionPK().getIdSubvencion() + 1;
            } else {
                i = 1;
            }
            SubvencionPK clave = new SubvencionPK(i, p.getIdProyecto());
            subvencion.setSubvencionPK(clave);
            subvencion.setProyecto(p);
            subvencion.setResolucion("P");
            getContP().crearEntidad(subvencion);
            return true;
        }else
            return false;
    }

    /**
     * Método que guarda una subvención en la lista.
     * @param subvencion Subvención que vamos a guardar. 
     */
    public void guardarSubvencionLista(Subvencion subvencion) {
        subvenciones.add(subvencion);
    }

    /**
     * Método que edita una subvención.
     * @param subvencion subvención que vamos a editar.
     * @return true si se ha editado correctamente.
     * false si no se ha editado correctamente.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    public boolean editarSubvencion(Subvencion subvencion) throws IllegalOrphanException, NonexistentEntityException, Exception {
        Proyecto p= subvencion.getProyecto();
        if(p==null){
            return false;
        }
        if(subvencion.getEntidad()!=null && subvencion.getFechaPresentacion()!=null && getContP().obtenerEntidad(Proyecto.class, p.getIdProyecto())!=null 
                && (p.esProyectoCooperacion() || p.esProyectoSensibilizacion())){
            if (subvencion.getSubvencionPK() != null) {
                getContP().editarEntidad(subvencion);
                return true;
            }
        }
        return false;
    }

    /**
     * Método que borra una subvención.
     * @param subvencion subvención que vamos a borrar.
     * @return true si se ha borrado correctamente o false, si no es así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException 
     */
    public boolean borrarSubvencion(Subvencion subvencion) throws IllegalOrphanException, NonexistentEntityException {
        //Borramos la subvencion si esta existe y no está concedida
        if (!subvencion.estaConcedida() && !subvencion.estaRechazada()) {
            getContP().destroyEntidad(Subvencion.class, subvencion.getSubvencionPK());
            return true;
        } else {
            return false;
        }
    }

    /**
     * Método que borra una lista de subvenciones.
     * @param subvenciones lista de subvenciones que vamos a borrar.
     * @return true si se han borrado todas correctamente o false si no ha sido así.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException 
     */
    public boolean borrarSubvenciones(List<Subvencion> subvenciones) throws IllegalOrphanException, NonexistentEntityException {
        for (int i = subvenciones.size() - 1; i >= 0; i--) {
            if (!borrarSubvencion(subvenciones.get(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * Método que pone las subvenciones que estaban pendientes a rechazadas.
     * @param subvenciones lista de subvenciones que queremos modificar.
     * @throws IllegalOrphanException
     * @throws NonexistentEntityException
     * @throws Exception 
     */
    public void establecerSubvencionesRechazadas(List<Subvencion> subvenciones) throws IllegalOrphanException, NonexistentEntityException, Exception {
        for (Subvencion s : subvenciones) {
            if (s.estaPendiente()) {
                s.setResolucion("R");
                editarSubvencion(s);
            }
        }
    }

    /**
     * Método que crea los subvenciones que están guardados en la lista.
     * @param proyecto proyecto al que pertenecen los apadrinados.
     * @throws PreexistingEntityException
     * @throws Exception 
     */
    public void crearListaSubvenciones(Proyecto proyecto) throws PreexistingEntityException, Exception {
        if (subvenciones != null) {
            for (Subvencion subvencion : subvenciones) {
                guardarSubvencion(subvencion, proyecto);
            }
        }
        subvenciones = new ArrayList<Subvencion>();
    }

    /**
     * Método que devuelve la lista de subvenciones que existen en la base de datos.
     * @return lista de proyectos.
     */
    public List<Subvencion> obtenerSubvenciones() {
        return (List<Subvencion>) getContP().obtenerEntidades(Subvencion.class);
    }

    /**
     * Método que devuelve una lista de subvenciones que pertenecen a 
     * proyectos de un determinado tipo.
     * @param tipo tipo del proyecto al que pertenecen las subvenciones. 
     * @return lista de subvenciones.
     */
    public List<Subvencion> listaSubvenciones(String tipo) {
        List<Subvencion> listaSubvenciones = new ArrayList<Subvencion>();
        for (Subvencion subvencion : obtenerSubvenciones()) {
            //Si la subvencion pertenece a un proyecto del tipo buscado y el proyecto al que pertenece esta activo la metemos en la lista
            if (subvencion.getProyecto().getTipo().compareTo(tipo) == 0 && subvencion.getProyecto().getActivo()) {
                listaSubvenciones.add(subvencion);
            }
        }
        return listaSubvenciones;
    }

    /**
     * Método que devuelve la lista de subvenciones.
     * @return lista de subvenciones.
     * @see #setSubvenciones
     */
    public List<Subvencion> getSubvenciones() {
        return subvenciones;
    }

    /**
     * Método que establece un nuevo valor a la lista de subvenciones.
     * @param subvenciones nuevo valor para lista. 
     * @see #getSubvenciones
     */
    public void setSubvenciones(List<Subvencion> subvenciones) {
        this.subvenciones = subvenciones;
    }
}